package com.ceair.flight.refund.service.appmobile.impl;

import com.ceair.flight.refund.dto.appmoblie.AirInfo;
import com.ceair.flight.refund.dto.appmoblie.Apply;
import com.ceair.flight.refund.dto.appmoblie.Attachment;
import com.ceair.flight.refund.dto.appmoblie.CalculateFeeReq;
import com.ceair.flight.refund.dto.appmoblie.CalculateFeeRes;
import com.ceair.flight.refund.dto.appmoblie.PaxInfo;
import com.ceair.flight.refund.dto.appmoblie.RefundDetailInfo;
import com.ceair.flight.refund.dto.appmoblie.SubOrderInfo;
import com.ceair.flight.refund.dto.appmoblie.Tax;
import com.ceair.flight.refund.dto.external.ApplyRequest;
import com.ceair.flight.refund.dto.external.ApplyResponse;
import com.ceair.flight.refund.dto.external.RefundDocs;
import com.ceair.flight.refund.dto.external.RefundPriceResult;
import com.ceair.flight.refund.dto.external.RefundPriceResultList;
import com.ceair.flight.refund.dto.external.RefundableRequest;
import com.ceair.flight.refund.dto.external.RefundableResult;
import com.ceair.flight.refund.location.dao.IFlightOrderDao;
import com.ceair.flight.refund.location.dt.enums.ApplyReason;
import com.ceair.flight.refund.location.dt.enums.ApplyUserType;
import com.ceair.flight.refund.location.model.FlightOrderDO;
import com.ceair.flight.refund.location.model.OrderDO;
import com.ceair.flight.refund.location.model.PaxDO;
import com.ceair.flight.refund.location.model.SegmentDO;
import com.ceair.flight.refund.location.model.TaxFeeDO;
import com.ceair.flight.refund.location.model.TicketDO;
import com.ceair.flight.refund.location.service.IRefundLocationService;
import com.ceair.flight.refund.service.IOrderService;
import com.ceair.flight.refund.service.IRefundTicketService;
import com.ceair.flight.refund.service.appmobile.IAppRefundCalculatorService;
import com.ceair.flight.refund.util.CeairUtil;
import com.ceair.flight.refund.util.Constants;
import com.ceair.flight.refund.util.GsonUtil;
import com.ceair.flight.refund.util.StringUtil;
import com.ceair.muibe.provider.tkt.DetrTktInfo;
import com.ceair.muibe.provider.tkt.DetrTktNoReq;
import com.ceair.muibe.provider.tkt.DetrTktNoRes;
import com.ceair.muibe.provider.tkt.OutTktService;
import com.ceair.muservice.basicdata.dto.channel.ChannelManageDto;
import com.ceair.muservice.common.exception.MuServiceException;
import com.ceair.muservice.filemanager.dto.file.BaseUploadReq;
import com.ceair.muservice.filemanager.dto.file.BaseUploadRes;
import com.ceair.muservice.filemanager.dto.refund.BatchUploadReq;
import com.ceair.muservice.filemanager.dto.refund.BatchUploadRes;
import com.ceair.muservice.filemanager.feign.IFileManager;
import com.google.gson.Gson;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

@Service("appRefundCalculatorService")
@Path("/")
public class AppRefundCalculatorServiceImpl implements IAppRefundCalculatorService {

    private static final Logger LOG = LoggerFactory.getLogger(AppRefundCalculatorServiceImpl.class);

    @Autowired
    private IRefundLocationService refundLocationService;

    @Autowired
    private OutTktService outTktService;

    @Autowired
    private IRefundTicketService refundTicketService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IFlightOrderDao flightOrderDao;

    @Autowired
    private IFileManager filemanager;

    @Override
    @POST
    @Path("/calculateFee")
    @Consumes({"application/json"})
    @Produces(MediaType.APPLICATION_JSON)
    @HystrixCommand(
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "120000")}
    )
    public CalculateFeeRes calculateFee(CalculateFeeReq req) {
        LOG.info("refund calculator input:{}", GsonUtil.toJson(req));
        CalculateFeeRes res = new CalculateFeeRes();
        boolean isSuccess = checkParam(req);
        if (!isSuccess) {
            res.setResultCode(Constants.ERROR_CODE);
            res.setResultMsg(Constants.PARAMS_ERROR_MSG);
            return res;
        }

        List<SubOrderInfo> subOrderInfos = req.getSubProductList();
        List<Long> psgIds = new ArrayList<>();
        for (SubOrderInfo subOrderInfo : subOrderInfos) {
            String subOrderType = subOrderInfo.getSubOrderType();
            if (Constants.PRO_TYPE_AIR.equals(subOrderType)) {
                String subId = subOrderInfo.getSubId();
                Long id = Long.parseLong(subId);
                psgIds.add(id);
            }
        }

        String stageCode = req.getDruidStageCode();
        try {
            OrderDO orderDO = orderService.queryFlightOrderDetail(req.getApplyInfo().getOrderNo());
            List<PaxDO> refundPaxList = new ArrayList<>();
            Set<FlightOrderDO> flightOrderDOS = orderDO.getFlightOrders();
            for (FlightOrderDO flightOrderDO : flightOrderDOS) {
                Set<PaxDO> paxDOS = flightOrderDO.getPaxs();
                for (PaxDO paxDO : paxDOS) {
                    Integer status = paxDO.getModifySt();
                    if (2 == status) {//开票状态
                        Long paxId = paxDO.getPassengerId();
                        if (psgIds.contains(paxId)) {
                            refundPaxList.add(paxDO);
                        }
                    }
                }
            }
            Map<String, Set<String>> tktMap = new HashMap<>();
            for (PaxDO paxDO : refundPaxList) {
                String tktStr = paxDO.getTktNo();
                String flightOrderNo = paxDO.getFlightOrderNo();
                Set<String> tktNoSet = tktMap.get(flightOrderNo);
                if (tktNoSet == null) {
                    tktNoSet = new HashSet<>();
                    tktMap.put(flightOrderNo, tktNoSet);
                }
                tktNoSet.add(tktStr);
            }

            List<RefundPriceResultList> resultList = new ArrayList<>();
            if ("refund".equals(stageCode)) {//退票申请
                if (refundPaxList.isEmpty()) {
                    res.setResultCode(Constants.ERROR_CODE);
                    res.setResultMsg("申请退票失败");
                    return res;
                }
                resultList = apply(req, orderDO, refundPaxList, tktMap);
                if (CollectionUtils.isEmpty(resultList)) {
                    res.setResultCode(Constants.ERROR_CODE);
                    res.setResultMsg("申请退票失败");
                    LOG.error("退票申请失败，params:{}",GsonUtil.toJson(tktMap));
                    return res;
                }
            }else if ("calcFee".equals(stageCode)){
                resultList = calFee(req, tktMap);
                if (CollectionUtils.isEmpty(resultList)) {
                    res.setResultCode(Constants.ERROR_CODE);
                    res.setResultMsg("退票费用计算失败");
                    LOG.error("退票费用计算失败，params:{}",GsonUtil.toJson(tktMap));
                    return res;
                }
            }
            res = buildResult(req, resultList, refundPaxList, tktMap, orderDO);

        } catch (Exception e) {
            LOG.error(e.getMessage(), e);
            res.setResultCode("1");
            if ("refund".equals(stageCode)) {
                res.setResultMsg("申请退票失败");
            }else {
                res.setResultMsg("退票费用计算失败");
            }
            return res;
        } catch (Error error) {
            LOG.error(error.getMessage(), error);
            res.setResultCode("1");
            if ("refund".equals(stageCode)) {
                res.setResultMsg("申请退票失败");
            }else {
                res.setResultMsg("退票费用计算失败");
            }
            return res;
        }

        return res;
    }

    private CalculateFeeRes buildResult(CalculateFeeReq req, List<RefundPriceResultList> resultList, List<PaxDO> refundPaxList,
                                        Map<String, Set<String>> tktMap, OrderDO orderDO) throws MuServiceException {
        CalculateFeeRes res = new CalculateFeeRes();
        Long applyType = req.getApplyInfo().getApplyType();
        RefundDetailInfo refundDetailInfo = new RefundDetailInfo();
        BigDecimal totalRefundAmount = BigDecimal.ZERO;//总退款金额
        Long totalRefundPoint = 0l;//总退票积分
        BigDecimal totalPoundageAmount = BigDecimal.ZERO;//总退票手续费
        double totalPoundagePoint = 0l;//积分手续费
        List<PaxInfo> paxInfoList = new ArrayList<>();
        for (PaxDO paxDO : refundPaxList) {
            BigDecimal paxRefundAmount = BigDecimal.ZERO;//当前乘客退款金额
            double paxRefundPoint = 0;//当前乘客退积分
            BigDecimal paxPoundageAmount = BigDecimal.ZERO;//当前乘客退票手续费
            double paxPoundagePoint = 0;//当前乘客积分手续费
            Set<TicketDO> tktSet = paxDO.getTickets();
            Set<SegmentDO> segmentDOS = paxDO.getSegments();
            List<AirInfo> airInfoList = new ArrayList<>();
            String tktNo = paxDO.getTktNo();
            boolean isRefundable = false;
            RefundableResult refundableResult = null;
            BigDecimal tktRefundAmount = BigDecimal.ZERO;//当前机票退款金额
            Long tktRefundPoint = 0l;//当前机票退积分
            BigDecimal tktPoundageAmount = BigDecimal.ZERO;//当前机票退票手续费
            Long tktPoundagePoint = 0l;//当前乘客积分手续费
            for (RefundPriceResultList refundPriceResultList : resultList) {
                refundableResult = refundPriceResultList.getSingleResult(tktNo);//根据票号获取是否可退信息
                if (refundableResult == null) {
                    LOG.error("refundableResult is null,tktNo:{},req:{}",tktNo,GsonUtil.toJson(req));
                    res.setResultCode(Constants.ERROR_CODE);
                    res.setResultMsg(Constants.APP_SERVER_ERROR_MSG);
                    return res;
                }
                RefundPriceResult refundPriceResult = null;
                if (Constants.OTA_VOLRFD_CD.equals(applyType) || 10L == applyType) {//获取退票费用相关信息
                    //自愿退票
                    refundPriceResult = refundPriceResultList.getVolPrice(tktNo);
                } else {
                    refundPriceResult = refundPriceResultList.getInvolPrice(tktNo);
                }
                if (refundPriceResult == null) {
                    LOG.error("AppRefundCalculator buildResult error,refundPriceResult can't find,ticketNo:{}", tktNo);
                    continue;
                }
                //总退票费用包括可退金额和税费
                BigDecimal refundAmount = refundPriceResult.getRefundAmount() == null? new BigDecimal("0"):refundPriceResult.getRefundAmount();
                BigDecimal feeAmount = refundPriceResult.getFeeAmount() == null? new BigDecimal("0"):refundPriceResult.getFeeAmount();
                Long pointAmount = refundPriceResult.getPointAmount() == null?0L:refundPriceResult.getPointAmount();
                totalRefundAmount = totalRefundAmount.add(refundAmount);
                totalPoundageAmount = totalPoundageAmount.add(feeAmount);
                totalRefundPoint = totalRefundPoint + pointAmount;

                //退给旅客的费用包括可退金额和税费
                paxRefundAmount = paxRefundAmount.add(refundAmount);
                paxPoundageAmount = paxPoundageAmount.add(feeAmount);
                paxRefundPoint = paxRefundPoint + pointAmount;
                //当前机票退票费用包括可退金额和税费
                tktRefundAmount = refundAmount;//当前机票退款金额
                tktRefundPoint = pointAmount;//当前机票退积分
                tktPoundageAmount = feeAmount;//当前机票退票手续费
                tktPoundagePoint = 0l;//当前乘客积分手续费
                isRefundable = true;
                break;
            }
            if (isRefundable) {
                TicketDO ticketDO = tktSet.iterator().next();
                AirInfo airInfo = new AirInfo();
                airInfo.setTicketNo(tktNo);
                airInfoList.add(airInfo);
                airInfo.setCurrency(paxDO.getCurrency());
                airInfo.setPoundageAmount(tktPoundageAmount.doubleValue());
                airInfo.setRefundAmount(tktRefundAmount.doubleValue());
                airInfo.setRefundPoint(tktRefundPoint.doubleValue());
                airInfo.setPoundagePoint(tktPoundagePoint.doubleValue());
                airInfo.setTktSegStatus(ticketDO.getTktSt());
                List<Tax> taxes = new ArrayList<>();
                for (SegmentDO segmentDO : segmentDOS) {
                    if (segmentDO.getSegSq() >= refundableResult.getRefundableIndex()) {
                        Set<TaxFeeDO> segTaxFeeSet = segmentDO.getTaxFees();
                        for (TaxFeeDO taxFeeDO : segTaxFeeSet) {
                            Tax tax = new Tax();
                            String taxFeeStr = taxFeeDO.getTaxAm() == null ? "0" : taxFeeDO.getTaxAm().toString();
                            tax.setAmount(Double.parseDouble(taxFeeStr));
                            tax.setCurrency(taxFeeDO.getCurrency());
                            tax.setName(taxFeeDO.getPaxTp());
                            tax.setOriginal_amount(tax.getAmount());
                            tax.setTaxFee(tax.getAmount());
                            taxes.add(tax);
                        }
                    }
                }
                airInfo.setTax(taxes);

            }
            if (airInfoList.isEmpty()) {
                continue;
            }
            PaxInfo paxInfo = new PaxInfo();
            paxInfo.setPointTp(paxDO.getPointTp());
            paxInfo.setPaxName(paxDO.getPaxFullName());
            paxInfo.setPaxId(paxDO.getPassengerId());
            paxInfo.setPayTktAmt(paxDO.getScny() == null ? 0 : paxDO.getScny().doubleValue());
            paxInfo.setPayTaxAmt(paxDO.getTaxAm() == null ? 0 : paxDO.getTaxAm().doubleValue());
            paxInfo.setChangeDateAmt(paxDO.getChangeAm() == null ? 0 : paxDO.getChangeAm().doubleValue());
            paxInfo.setPointAmt(paxDO.getPointAmount() == null ? 0 : paxDO.getPointAmount().doubleValue());
            paxInfo.setIdNo(paxDO.getPassNo());
            paxInfo.setWithHoldAmt(paxPoundageAmount.doubleValue());
            paxPoundagePoint = paxDO.getPointAmount().doubleValue() - paxRefundPoint;
            paxInfo.setWithHoldPoint(paxPoundagePoint);
            totalPoundagePoint = totalPoundagePoint + paxPoundagePoint;
            paxInfo.setRefundPoint(paxRefundPoint);
            paxInfo.setRefundTotal(paxRefundAmount.doubleValue());
            paxInfo.setAirInfo(airInfoList);
            paxInfoList.add(paxInfo);
        }
        refundDetailInfo.setPaxList(paxInfoList);
        refundDetailInfo.setTotalRefundAmount(totalRefundAmount.doubleValue());
        refundDetailInfo.setTotalPoundageAmount(totalPoundageAmount.doubleValue());
        refundDetailInfo.setTotalRefundPoint(Double.parseDouble(totalRefundPoint.toString()));
        refundDetailInfo.setTotalPoundagePoint(totalPoundagePoint);
        res.setRefundDetailInfo(refundDetailInfo);
        res.setResultCode(Constants.SUCCESS_CODE);
        res.setResultMsg(Constants.SUCCESS_MSG);
        return res;
    }

    private List<RefundPriceResultList> apply(CalculateFeeReq request, OrderDO orderDO, List<PaxDO> refundPaxList, Map<String, Set<String>> tktMap) throws MuServiceException {

        List<RefundPriceResultList> result = new ArrayList<>();
        for (Map.Entry<String, Set<String>> entry : tktMap.entrySet()) {
            String flightOrderNo = entry.getKey();
            Set<String> tktSet = entry.getValue();
            ApplyRequest applyRequest = new ApplyRequest();

            applyRequest.setCreateId(request.getCreateId());
            applyRequest.setFfpNo(request.getFfpNo());
            applyRequest.setTickets(tktSet);
            applyRequest.setFlightOrderNo(flightOrderNo);
            //applyRequest.setClaimerId(claimerId);
            applyRequest.setSalesChannel(request.getSalesChannel());
            applyRequest.setChannelNo(request.getSalesChannel());
            applyRequest.setClaimerName(request.getApplyInfo().getApplyPerson());
            applyRequest.setClaimerPhone(request.getApplyInfo().getMobile());
//            applyRequest.setClaimerEmail(request.getApplyInfo());
            applyRequest.setClaimerType(ApplyUserType.SYSTEM);
            applyRequest.setClaimSource(request.getRequestIp()); //申请退票用户IP
            ChannelManageDto channelManageDto = refundLocationService.findChannelByCode(request.getSalesChannel());
            applyRequest.setCountry(channelManageDto.getNationCode());//国家
            applyRequest.setLanguage(channelManageDto.getLanguageCode());//语言
            //退票类型:281：自愿退票 282：非自愿退票；283：航班延误或取消（航空公司原因）;284 当日作废；285突发事件；286：病退 287：另购客票
            String applyType = String.valueOf(request.getApplyInfo().getApplyType());
            switch (applyType) {
                case "281":
                case "10":
                    applyRequest.setClaimReason(ApplyReason.getByCode("10"));
                    break;
                case "282":
                case "284":
                case "285":
                case "24":
                    applyRequest.setClaimReason(ApplyReason.getByCode("24"));
                    break;
                case "283":
                case "21":
                    applyRequest.setClaimReason(ApplyReason.getByCode("21"));
                    break;
                case "286":
                case "22":
                    applyRequest.setClaimReason(ApplyReason.getByCode("22"));
                    Set<Attachment> attachments = request.getApplyInfo().getAttachments();
                    List<RefundDocs> attachmentList = new ArrayList<RefundDocs>();
                    if (!CollectionUtils.isEmpty(attachments)) {
                        BatchUploadReq batchUploadReq = new BatchUploadReq();
                        batchUploadReq.setSalesChannel(request.getSalesChannel());
                        List<BaseUploadReq> files = new ArrayList<>();
                        batchUploadReq.setFiles(files);
                        for (Attachment refundAttachment : attachments) {
                            BaseUploadReq req = new BaseUploadReq();
                            req.setSalesChannel(request.getSalesChannel());
                            req.setFileName(refundAttachment.getName());
                            req.setFileData(refundAttachment.getContent());
                            files.add(req);
                        }
                        BatchUploadRes batchUploadRes = filemanager.batchUploadAttachments(batchUploadReq);
                        if ("0".equals(batchUploadRes.getResultCode())){
                            List<BaseUploadRes> baseUploadRes = batchUploadRes.getFiles();
                            if (!CollectionUtils.isEmpty(baseUploadRes) && baseUploadRes.size() == files.size()){
                                baseUploadRes.stream().forEach(item ->{
                                    long fileId = item.getId();
                                    String fileName = item.getFileName();
                                    RefundDocs refundDocs = new RefundDocs();
                                    //TODO 将Content 附件内容 保存至cdn返回保存路径,@ 王珽
                                    String url = String.valueOf(fileId);
                                    refundDocs.setAttchments(url);
                                    refundDocs.setContentDesc(fileName);
                                    attachmentList.add(refundDocs);
                                });
                            }else {
                                LOG.error("upload refundAttachment error:{}",GsonUtil.toJson(batchUploadReq));
                                return result;
                            }
                        }else {
                            LOG.error("upload refundAttachment error:{}",GsonUtil.toJson(batchUploadReq));
                            return result;
                        }
                    }
                    applyRequest.setAttachments(attachmentList);
                    break;
                case "287":
                case "23":
                    applyRequest.setClaimReason(ApplyReason.getByCode("23"));
                    //另购客票号
                    String repurchaseTickets = request.getApplyInfo().getRepurchaseTicket();
                    LOG.info("另购客票 :" + repurchaseTickets);
                    String[] repurchaseTicket = repurchaseTickets.split(",");
                    if (repurchaseTicket.length == 0 || null == repurchaseTicket) {
                        LOG.error("退票原因:287 另购客票,未填写另购客票号");
                        return result;
                    }
                    DetrTktNoReq detrTktNoReq = new DetrTktNoReq();
                    //TODO 确认渠道,否则报错
                    detrTktNoReq.setUser(CeairUtil.getUserInfo(request.getSalesChannel()));
                    for (String ticket : repurchaseTicket) {
                        detrTktNoReq.setTktNo(ticket);
                        //TODO 从航信提取另购客票号,服务未起
                        DetrTktNoRes detrTktNoRes = this.outTktService.detrTktNo(detrTktNoReq);
                        if (null == detrTktNoRes || null == detrTktNoRes.getTktInfo()) {
                            LOG.error("另购客票号: 不存在,从航信未查询到另购客票,不允许以另购客票为理由退票:{}",GsonUtil.toJson(detrTktNoReq));
                            return result;
                        }
                        LOG.info("大订单号：" + request.getApplyInfo().getOrderNo() + " == 另购票号" + ticket + "票号查询结果：" + GsonUtil.toJson(detrTktNoRes));
                        //新购客票
                        DetrTktInfo tktInfo = detrTktNoRes.getTktInfo();
                        //判断退票信息与另购票信息
                        for (PaxDO pax : refundPaxList) {
                            //另购票规则
                            if (flightOrderNo.equals(pax.getFlightOrderNo())) {
                                //退票销售价
                                BigDecimal scny = pax.getScny();
                                //另购客票总价
                                BigDecimal totalAmount = new BigDecimal(tktInfo.getTotalAmount());
                                if (totalAmount.compareTo(scny) == -1) {
                                    LOG.error("退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
                                    return result;
                                }
                                //退票乘客姓名
                                String name = pax.getPassengerFirstName() + pax.getPassengerMiddleName() + pax.getPassengerLastName();
                                //新购客票乘客姓名
                                String passengerName = tktInfo.getPassengerName();
                                if (!name.equals(passengerName)) {
                                    LOG.error("退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
                                    return result;
                                }
                                //退票乘客航程
                                //退票乘客航班
                                //退票乘客日期
                                //退票乘客机票价格
                                //另购票是否已使用
                            }
                        }
                    }
                    break;
                case "25":
                    applyRequest.setClaimReason(ApplyReason.getByCode("25"));
                    break;
                case "26":
                    applyRequest.setClaimReason(ApplyReason.getByCode("26"));
                    break;
                case "50":
                    applyRequest.setClaimReason(ApplyReason.getByCode("50"));
                    break;
                case "51":
                    applyRequest.setClaimReason(ApplyReason.getByCode("51"));
                    break;
                default:
                    applyRequest.check();
                    break;
            }
            applyRequest.setClaimDesc(request.getApplyInfo().getReason());
            ApplyResponse applyRfdTkt = refundTicketService.applyRfdTkt(applyRequest);
            RefundPriceResultList refundPriceResultList =applyRfdTkt.getRefundPriceResultList();
            if (!applyRfdTkt.isSuccess() || null == refundPriceResultList) {
                LOG.error("Refund ticket error:{}", GsonUtil.toJson(applyRequest));
                return result;
            }
            result.add(refundPriceResultList);
        }
        return result;
    }

//    private CalculateFeeRes apply(CalculateFeeReq request, OrderDO orderDO, List<PaxDO> refundPaxList, Map<String, Set<String>> tktMap) throws MuServiceException {
//
//        CalculateFeeRes refundRes = new CalculateFeeRes();
//        refundRes.setResultCode(Constants.SUCCESS_CODE);
//        refundRes.setResultMsg(Constants.SUCCESS_MSG);
//        for (Map.Entry<String, Set<String>> entry : tktMap.entrySet()) {
//            String flightOrderNo = entry.getKey();
//            Set<String> tktSet = entry.getValue();
//            ApplyRequest applyRequest = new ApplyRequest();
//
//
//            applyRequest.setTickets(tktSet);
//            applyRequest.setFlightOrderNo(flightOrderNo);
//            //applyRequest.setClaimerId(claimerId);
//            applyRequest.setSalesChannel(request.getSalesChannel());
//            applyRequest.setChannelNo(request.getSalesChannel());
//            applyRequest.setClaimerName(request.getApplyInfo().getApplyPerson());
//            applyRequest.setClaimerPhone(request.getApplyInfo().getMobile());
////            applyRequest.setClaimerEmail(request.getApplyInfo());
//            applyRequest.setClaimerType(ApplyUserType.SYSTEM);
//            applyRequest.setClaimSource(request.getRequestIp()); //申请退票用户IP
//            ChannelManageDto channelManageDto = refundLocationService.findChannelByCode(request.getSalesChannel());
//            applyRequest.setCountry(channelManageDto.getNationCode());//国家
//            applyRequest.setLanguage(channelManageDto.getLanguageCode());//语言
//            //退票类型:281：自愿退票 282：非自愿退票；283：航班延误或取消（航空公司原因）;284 当日作废；285突发事件；286：病退 287：另购客票
//            String applyType = String.valueOf(request.getApplyInfo().getApplyType());
//            switch (applyType) {
//                case "281":
//                case "10":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("10"));
//                    break;
//                case "282":
//                case "284":
//                case "285":
//                case "24":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("24"));
//                    break;
//                case "283":
//                case "21":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("21"));
//                    break;
//                case "286":
//                case "22":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("22"));
//                    Set<Attachment> attachments = request.getApplyInfo().getAttachments();
//                    List<RefundDocs> attachmentList = new ArrayList<RefundDocs>();
//                    if (!CollectionUtils.isEmpty(attachments)) {
//                        BatchUploadReq batchUploadReq = new BatchUploadReq();
//                        batchUploadReq.setSalesChannel(request.getSalesChannel());
//                        List<BaseUploadReq> files = new ArrayList<>();
//                        batchUploadReq.setFiles(files);
//                        for (Attachment refundAttachment : attachments) {
//                            BaseUploadReq req = new BaseUploadReq();
//                            req.setSalesChannel(request.getSalesChannel());
//                            req.setFileName(refundAttachment.getName());
//                            req.setFileData(refundAttachment.getContent());
//                            files.add(req);
//                        }
//                        BatchUploadRes batchUploadRes = filemanager.batchUploadAttachments(batchUploadReq);
//                        if ("0".equals(batchUploadRes.getResultCode())){
//                            List<BaseUploadRes> baseUploadRes = batchUploadRes.getFiles();
//                            if (!CollectionUtils.isEmpty(baseUploadRes) && baseUploadRes.size() == files.size()){
//                                baseUploadRes.stream().forEach(item ->{
//                                    long fileId = item.getId();
//                                    String fileName = item.getFileName();
//                                    RefundDocs refundDocs = new RefundDocs();
//                                    //TODO 将Content 附件内容 保存至cdn返回保存路径,@ 王珽
//                                    String url = String.valueOf(fileId);
//                                    refundDocs.setAttchments(url);
//                                    refundDocs.setContentDesc(fileName);
//                                    attachmentList.add(refundDocs);
//                                });
//                            }else {
//                                refundRes.setResultCode(Constants.ERROR_CODE);
//                                refundRes.setResultMsg("退票申请失败");
//                                return refundRes;
//                            }
//                        }else {
//                            refundRes.setResultCode(Constants.ERROR_CODE);
//                            refundRes.setResultMsg("退票申请失败");
//                            return refundRes;
//                        }
//                    }
//                    applyRequest.setAttachments(attachmentList);
//                    break;
//                case "287":
//                case "23":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("23"));
//                    //另购客票号
//                    String repurchaseTickets = request.getApplyInfo().getRepurchaseTicket();
//                    LOG.info("另购客票 :" + repurchaseTickets);
//                    String[] repurchaseTicket = repurchaseTickets.split(",");
//                    if (repurchaseTicket.length == 0 || null == repurchaseTicket) {
//                        LOG.error("退票原因:287 另购客票,未填写另购客票号");
//                        refundRes.setResultMsg("失败原因:另购客票,未填写另购客票号");
//                        refundRes.setResultCode("1");
//                        return refundRes;
//                    }
//                    DetrTktNoReq detrTktNoReq = new DetrTktNoReq();
//                    //TODO 确认渠道,否则报错
//                    detrTktNoReq.setUser(CeairUtil.getUserInfo(request.getSalesChannel()));
//                    for (String ticket : repurchaseTicket) {
//                        detrTktNoReq.setTktNo(ticket);
//                        //TODO 从航信提取另购客票号,服务未起
//                        DetrTktNoRes detrTktNoRes = this.outTktService.detrTktNo(detrTktNoReq);
//                        if (null == detrTktNoRes || null == detrTktNoRes.getTktInfo()) {
//                            LOG.error("另购客票号: 不存在,从航信未查询到另购客票,不允许以另购客票为理由退票");
//                            refundRes.setResultMsg("失败原因:另购客票号: 不存在,从航信未查询到另购客票,不允许以另购客票为理由退票");
//                            refundRes.setResultCode("1");
//                            return refundRes;
//                        }
//                        LOG.info("大订单号：" + request.getApplyInfo().getOrderNo() + " == 另购票号" + ticket + "票号查询结果：" + GsonUtil.toJson(detrTktNoRes));
//                        //新购客票
//                        DetrTktInfo tktInfo = detrTktNoRes.getTktInfo();
//                        //判断退票信息与另购票信息
//                        for (PaxDO pax : refundPaxList) {
//                            //另购票规则
//                            if (flightOrderNo.equals(pax.getFlightOrderNo())) {
//                                //退票销售价
//                                BigDecimal scny = pax.getScny();
//                                //另购客票总价
//                                BigDecimal totalAmount = new BigDecimal(tktInfo.getTotalAmount());
//                                if (totalAmount.compareTo(scny) == -1) {
//                                    LOG.error("退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
//                                    refundRes.setResultMsg("失败原因:退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
//                                    refundRes.setResultCode("1");
//                                    return refundRes;
//                                }
//                                //退票乘客姓名
//                                String name = pax.getPassengerFirstName() + pax.getPassengerMiddleName() + pax.getPassengerLastName();
//                                //新购客票乘客姓名
//                                String passengerName = tktInfo.getPassengerName();
//                                if (!name.equals(passengerName)) {
//                                    LOG.error("退票原因:287 ;另购客票销售价:" + totalAmount + "小于" + "退票客票销售价" + scny + ",不允许走287流程退票");
//                                    refundRes.setResultMsg("失败原因:乘客姓名不一致,退票乘客姓名 " + name + ",新购客票乘客姓名 " + passengerName);
//                                    refundRes.setResultCode("1");
//                                    return refundRes;
//                                }
//                                //退票乘客航程
//                                //退票乘客航班
//                                //退票乘客日期
//                                //退票乘客机票价格
//                                //另购票是否已使用
//                            }
//                        }
//                    }
//                    break;
//                case "25":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("25"));
//                    break;
//                case "26":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("26"));
//                    break;
//                case "50":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("50"));
//                    break;
//                case "51":
//                    applyRequest.setClaimReason(ApplyReason.getByCode("51"));
//                    break;
//                default:
//                    applyRequest.check();
//                    break;
//            }
//            applyRequest.setClaimDesc(request.getApplyInfo().getReason());
//            ApplyResponse applyRfdTkt = refundTicketService.applyRfdTkt(applyRequest);
//            if (!applyRfdTkt.isSuccess()) {
//                refundRes.setResultCode(Constants.ERROR_CODE);
//                refundRes.setResultMsg("退票申请失败");
//                return refundRes;
//            }
//        }
//        return refundRes;
//    }

    private List<RefundPriceResultList> calFee(CalculateFeeReq request, Map<String, Set<String>> tktMap) throws MuServiceException {
        List<RefundPriceResultList> result = new ArrayList<>();
        if (tktMap == null || tktMap.isEmpty()) {
            return result;
        }
        Long applyType = request.getApplyInfo().getApplyType();

        if (Constants.OTA_VOLRFD_CD.equals(applyType) || 10L == applyType) {
            //自愿退票
            for (Map.Entry<String, Set<String>> entry : tktMap.entrySet()) {
                String key = entry.getKey();
                Set<String> value = entry.getValue();
                RefundableRequest req = new RefundableRequest();
                req.setCreateId(request.getCreateId());
                req.setFfpNo(request.getFfpNo());
                req.setFlightOrderNo(key);
                req.setTickets(value);
                req.setSalesChannel(request.getSalesChannel());
                RefundPriceResultList refundPriceResultList = refundLocationService.calculateVolPrice(req);
                result.add(refundPriceResultList);
            }
        } else {
            //非自愿
            for (Map.Entry<String, Set<String>> entry : tktMap.entrySet()) {
                String key = entry.getKey();
                Set<String> value = entry.getValue();
                RefundableRequest req = new RefundableRequest();
                req.setCreateId(request.getCreateId());
                req.setFfpNo(request.getFfpNo());
                req.setFlightOrderNo(key);
                req.setTickets(value);
                req.setSalesChannel(request.getSalesChannel());
                RefundPriceResultList refundPriceResultList = refundLocationService.calculateInVolPrice(req);
                result.add(refundPriceResultList);
            }
        }
        return result;
    }

    private boolean checkParam(CalculateFeeReq req) {
        boolean result = true;
        Apply applyInfo = req.getApplyInfo();
        String druidStageCode = req.getDruidStageCode();
        String salesChannel = req.getSalesChannel();
        List<SubOrderInfo> subOrderInfoList = req.getSubProductList();
        if (StringUtil.isBlank(druidStageCode) || StringUtil.isBlank(salesChannel)) {
            return false;
        }
        if (applyInfo == null) {
            return false;
        }
        if (StringUtil.isBlank(applyInfo.getOrderNo())) {
            return false;
        }
        if (CollectionUtils.isEmpty(subOrderInfoList)) {
            return false;
        }

        return result;
    }
}
